<?php

define('code_error', -1);

/**
 * 手机端活动报名接口
 * Class enroll
 * @author lilei<LL_strive@163.com> 2017-05-02
 */
class enroll {

    /**
     * 手机端获得报名的活动信息
     *
     * @param $param    手机端参数
     */
    public static function index($param)
    {
//        $retVal = Session::init();
//        if ($retVal) {
//            Output::instance()->resultCode(code_access_denied);
//            return;
//        }

        /** 1. 数据校验 */
        $activityId = $param->actId;   // 需要活动的id
        $channelId  = $param->chanelId;     // ** 需要注意的是, 链接里的渠道参数是chanelId, 而不是channelId
        $fromUserId = $param->fromUserId;   // todo: 这个参数的来源有问题
        $fromUserId = $fromUserId ? $fromUserId : 0;
        $userId     = Session::$user['userId'];
        $customerId = Session::$user['customerId'];

        /** 2. 实例化数据模型 */
        Session::switchCustomer(0);
        $MiactivityModel = M('miactivity');
        $visitModel      = M('miactivity_visit');
        Session::switchCustomer($customerId);

        /** 3. 活动详细信息(主题, 时间, 收费) */
        // 注意活动的deleted等状态
        $MiactivityWhere['id']      = array('eq', $activityId);
        $MiactivityWhere['status']  = array('eq', 1);   // 0-停用,1-启用
        $MiactivityWhere['deleted'] = array('eq', 0);   // 0-未删除
        // 获得活动详细信息
        $activity = $MiactivityModel->where($MiactivityWhere)->find();

        // 判断报名状态
        $nowTime = date('Y-m-d H:i:s');
        if ($nowTime < $activity['startTime']) {
            $activity['activity_status'] = '报名未开始';
        } else if ($nowTime > $activity['endTime']) {
            $activity['activity_status'] = '报名已结束';
        } else {
            $activity['activity_status'] = '报名中';
        }

        /** 4. 处理参与表数据 */
        $partakeId = self::check_partake($param);

        /*获取ip对应的信息*/
        $ipInfo = self::getIp_agent();
        // 数据插入浏览表
        $visitData = [
            'cid'   => $customerId,
            'activityId'    => $activityId,
            'partakeId'     => $partakeId,
            'channelId'     => $channelId,
            'userId'        => $userId,
            'fromUserId'    => $fromUserId,
            'deleted'       => 0,
            'ip_address'       => $ipInfo['ip_address'],
            'ip_city'       => $ipInfo['city'],
            'ip_province'       => $ipInfo['province'],
            'user_agent'       => $ipInfo['userAgent'],
            'createTime'    => date('Y-m-d H:i:s')
        ];
        $visitResult = $visitModel->add($visitData);

        // 这里帮前端转一下json
        $activity['code']    = code_success;
        $activity['jsonstr'] = json_decode($activity['jsonstr'], TRUE);
        $activity['jsonstr']['startTime'] = strtotime($activity['jsonstr']['startTime']);
        $activity['jsonstr']['endTime']   = strtotime($activity['jsonstr']['endTime']);
        $activity['startTime']  = strtotime($activity['startTime']);
        $activity['endTime']    = strtotime($activity['endTime']);
        $activity['createTime'] = strtotime($activity['createTime']);
        $activity['updateTime'] = strtotime($activity['updateTime']);
        // 增加当前userid, 分享是加入链接中, 即便为fromUserId
        $activity['userId']     = $userId;

        /** 5. 数据输出至手机页面 */
        Output::instance()->module("enroll", "index")->object($activity);
    }

    /**
     * 点击"我要报名"时一些验证(主要: 是否关注公众号, 是否已报名, 报名时间区域, 报名人数限制...)
     *
     * @param $param    手机端参数
     */
    public static function preEnroll($param)
    {
//        $retVal = Session::init();
//        if (!$retVal) {
//            Output::instance()->resultCode(code_access_denied);
//            return;
//        }

        /** 1. 数据校验 */
        // 需要活动的id, userid(为了直接判断是不是已经报名, userid手机端给不了)
        $activityId = $param->actId;
        // 好像给不了userId, -> 给openId(也给不了, Session中拿)
        $userId     = Session::$user['userId'];
        $customerId = Session::$user['customerId'];

        /** 2. 实例化数据模型 */
        Session::switchCustomer(0);
        $MiactivityModel = M('miactivity');
        $MibaomingModel  = M('mibaoming_info');
        Session::switchCustomer($customerId);
        $UserModel       = M('user');

        // 查询活动信息
        $MiactivityWhere['id']      = array('eq', $activityId);
        $MiactivityWhere['status']  = array('eq', 1);
        $MiactivityWhere['deleted'] = array('eq', 0);
        $activity = $MiactivityModel->where($MiactivityWhere)->find();
        $activity['jsonstr'] = json_decode($activity['jsonstr'], TRUE);

        /** 3. 报名限制信息 */
        // 3.1 用户是否已关注
        $UserWhere['id'] = array('eq', $userId);
        $result_user = $UserModel->where($UserWhere)->field('id, status')->find();

        if (($activity['jsonstr']['need_subscribe'] == 1)
            && (empty($result_user['status']) || in_array($result_user['status'], ['sharesubscribe', 'unsubscribe']))) {    // 未关注( => 已关注[subscribe|scansubscribe])
            $result = [
                'code'      => code_error,
                'status'    => 'error',
                'message'   => '请先关注',
                'submessage'=> ''   // 关注的二维码图片
            ];
            Output::instance()->object($result);
            return;
        }

        // 3.2 用户是否已报名
        $MibaomingWhere['activityId'] = array('eq', $activityId);
        $MibaomingWhere['userId']     = array('eq', $result_user['id']);
        $MibaomingWhere['cid']        = array('eq', $customerId);
        if ($activity['jsonstr']['isPay'] == 1) {   // 如果需要支付, 看支付状态
            $MibaomingWhere['payment_status'] = array('in', [1, 4]); // 1-支付成功,4-不需要支付
        }
        // 无论是否需要支付, 都要看审核状态(因为即便在不需要审核的时候, 审核状态也是1)
        $MibaomingWhere['verify_status'] = array('in', [0, 1]);      // 0-等待审核,1-审核成功

        // 判断该活动下这位用户是否报名
        $verify_status = $MibaomingModel->where($MibaomingWhere)->getField('verify_status');
        if (isset($verify_status)) {  // 已报名
            $result = [
                'code'      => code_error,
                'status'    => 'error',
                'message'   => ($verify_status == 1) ? '您已报名成功' : '您已报名, 请等待审核',
                'submessage'=> ''
            ];
            Output::instance()->object($result);
            return;
        }

        // 3.3 活动相关限制
        // 3.3.1 时间区域限制
        $time = date('Y-m-d H:i:s');
        if ($time < $activity['startTime'] || $time > $activity['endTime']) {   // 不在报名时间范围内
            $result = [
                'code'      => code_error,
                'status'    => 'error',
                'message'   => '不在报名时间内',
                'submessage'=> ''
            ];
            Output::instance()->object($result);
            return;
        }

        // 3.3.2 报名人数限制
        if ($activity['isLimitCount'] == 1) {   // 进行报名人数限制
            unset($MibaomingWhere['userId']);                        // 去掉对用户的筛选
            $MibaomingWhere['verify_status'] = array('eq', 1);       // 报名人数限制筛选已审核通过的
            $count = $MibaomingModel->where($MibaomingWhere)->count();

            if ($count >= $activity['limitCount']) { //  报名人数已满
                $result = [
                    'code'      => code_error,
                    'status'    => 'error',
                    'message'   => '报名人数已满',
                    'submessage'=> ''
                ];
                Output::instance()->object($result);
                return;
            }
        }

        /** 4. 正常情况返回 */
        $result = [
            'code'      => code_success,
            'status'    => 'success',
            'message'   => '报名信息正常',
            'submessage'=> ''
        ];
        Output::instance()->object($result);
        return;
    }

    /**
     * 手机端点击"提交"报名参加活动
     *
     * @param $param    手机端参数
     */
    public static function confirmEnroll($param)
    {
//        $retVal = Session::init();
//        if (!$retVal) {
//            Output::instance()->resultCode(code_access_denied);
//            return;
//        }

        /** 1. 数据校验 */
        $activityId = $param->actId;
        $fromUserId = $param->fromUserId;
        $fromUserId = $fromUserId ? $fromUserId : 0;
        $channelId  = $param->chanelId;
        $lat        = $param->lat;
        $lng        = $param->lng;
        $address_detail = $param->address_detail;
        $form_json_str  = $param->form_json_str;
        $form_json_str  = json_encode($form_json_str);
        $userId     = Session::$user['userId'];
        $openId     = Session::$user['userName'];
        $customerId = Session::$user['customerId'];

        /** 2. 实例化数据模型 */
        Session::switchCustomer(0);
        $MiactivityModel = M('miactivity');
        $partakeModel    = M('miactivity_partake');
        $MibaomingModel  = M('mibaoming_info');
        Session::switchCustomer($customerId);

        /** 2.1. 活动详情(判断是否需要支付, 是否需要审核) */
        // 注意活动的deleted等状态
        $MiactivityWhere['id']      = array('eq', $activityId);
        $MiactivityWhere['status']  = array('eq', 1);   // 0-停用,1-启用
        $MiactivityWhere['deleted'] = array('eq', 0);   // 0-未删除
        // 获得活动详细信息
        $jsonstr = $MiactivityModel->where($MiactivityWhere)->getField('jsonstr');
        $obj_jsonstr = json_decode($jsonstr, TRUE);

        /** 3. 信息存入数据表 */

        /*获取ip对应的信息*/
        $ipInfo = self::getIp_agent();

        // 3.1 信息插入参与表
        $partake_data = [
            'cid'       => $customerId,
            'userId'    => $userId,
            'fromUserId'    => $fromUserId,
            'activityId'    => $activityId,
            'channelId'     => $channelId,
            'deleted'       => '0',
            'createTime'    => date('Y-m-d H:i:s'),
            'lat'           => $lat,
            'lng'           => $lng,
            'address_detail'=> $address_detail,
            /*以下数据为新增*/
            'ip_address'       => $ipInfo['ip_address'],
            'ip_city'       => $ipInfo['city'],
            'ip_province'       => $ipInfo['province'],
            'user_agent'       => $ipInfo['userAgent']
        ];
        $partakeId = $partakeModel->add($partake_data);

        // 3.2 报名信息插入报名表
        $data = [
            'cid'               => $customerId,
            'partakeId'         => $partakeId,  // 上面插入参与表的id
            'activityId'        => $activityId,
            'userId'            => $userId,
            'form_json_str'     => $form_json_str,
            'charge'            => 0,   // 这里钱额还没支付, 应该在下面支付成功后回调中修改
            'payment_status'    => $obj_jsonstr['isPay'] ? 0 : 4,   // 0-待支付,1-已支付,2-退款成功,3-退款失败, 4-不需要支付
            'verify_status'     => $obj_jsonstr['need_check'] ? 0 : 1,   // 0-待审核,1-审核成功,2-审核失败
            'createTime'        => date('Y-m-d H:i:s'),
            'updateTime'        => date('Y-m-d H:i:s')
        ];
        $result = $MibaomingModel->add($data);
        // 3.3 刷新活动表参与量
        $partakeCountInc = $MiactivityModel->where(['id' => $activityId])->setInc('partakeCount');

        // 不需要支付和审核, 直接发送模板消息, 报名成功
        if (!$obj_jsonstr['isPay'] && !$obj_jsonstr['need_check']) {
            self::send_template_message($obj_jsonstr, $customerId, $activityId, $channelId, $openId);
        }

        /** 4. 返回报名结果 */
        if ($result) {
            $submessage = '';
            if ($obj_jsonstr['isPay'] == 1 && $obj_jsonstr['need_check'] == 1) {
                $submessage = '请支付后等待审核';
            } else if ($obj_jsonstr['need_check'] == 1) {
                $submessage = '请等待审核';
            }

            Output::instance()->object([
                'code'      => code_success,
                'status'    => 'success',
                'message'   => '报名成功',
                'submessage'=> $submessage
            ]);
            return;
        } else {
            Output::instance()->object([
                'code'      => code_error,
                'status'    => 'error',
                'message'   => '报名失败',
                'submessage'=> '服务异常'
            ]);
            return;
        }

    }

    /**
     * 支付完成后的回调(如果报名需要收费,则在微信支付成功后回调该方法,修改报名付费情况)
     * ** 这个方法只允许支付回调调用 **
     *
     * @param $param    {"userName":"oNIXfjucopaDo8IJ-yPiC3VD7bFk","price":"0.01","id":"40","oid":"143694"}
     *                  userName => 用户的openid
     *                  price    => 用户此次微信付款金额
     *                  id       => 在调用微信支付时,有传一个moduleId(这个id应该是没有用处,这里用它来传相应的活动id)
     *                  oid      => 项目底层封装了微信支付,但是需要订单支持,所以这种其他类的支付会调用创建一个隐藏的订单
     */
    public static function payCallBack($param)
    {
        /** 1. 获取必要数据 */
        $openid     = $param->userName;     // 这在回调中带入, 以此找出userId
        $price      = $param->price;
        $activityId = $param->id;
        $oid        = $param->oid;
        $customerId = Session::$user['customerId'];

        /** 2. 实例化数据模型 */
        Session::switchCustomer(0);
        $miactivityModel = M('miactivity');
        $MibaomingModel  = M('mibaoming_info');
        $productOrderModel = M('module_product_order');     // 修改订单参数
        Session::switchCustomer($customerId);
        $UserModel       = M('user');
        $userInfoModel   = M('user_info');

        // 2.1 通过用户openid获得id(userId)
        $UserWhere['openid'] = array('eq', $openid);
        $userId = $UserModel->where($UserWhere)->getField('id');

        /** 3. 更新wx_mibaoming_info表 */
        // 3.1 修改条件
        $where['cid']         = array('eq', $customerId);
        $where['activityId']  = array('eq', $activityId);
        $where['userId']      = array('eq', $userId);
        // 一个用户在这个cid下这个活动可能多种情况参加, 但是现在出去支付的, 一定是最新的这个, 所以取出第一条符合条件的id
        $baomingId = $MibaomingModel->where($where)->order('id desc')->limit(1)->getField('id');
        $where['id']          = array('eq', $baomingId);
        // 3.2 需要修改的数据
        $data = [
            'charge'            => $price,
            'payment_status'    => 1,
            'pay_result_str'    => json_encode($param),
            'updateTime'        => date('Y-m-d H:i:s')
        ];
        // 3.3 执行修改
        $result = $MibaomingModel->where($where)->save($data);

        /** 4. 修改订单参数 */
        $userInfoWhere['fromUserName'] = array('eq', $openid);
        $fullName = $userInfoModel->where($userInfoWhere)->getField('fullName');

        $productOrderWhere['id'] = array('eq', $oid);
        $productOrderData = [
            'fullName'  => $fullName,
            'status'    => 'ok'
        ];
        $result = $productOrderModel->where($productOrderWhere)->save($productOrderData);

        // 注意活动的deleted等状态
        $miactivityWhere['id']      = array('eq', $activityId);
        $miactivityWhere['status']  = array('eq', 1);   // 0-停用,1-启用
        $miactivityWhere['deleted'] = array('eq', 0);   // 0-未删除
        // 获得活动详细信息
        $jsonstr = $miactivityModel->where($miactivityWhere)->getField('jsonstr');
        $obj_jsonstr = json_decode($jsonstr, TRUE);

        // 支付成功, 不需要审核, 发送模板消息, 报名成功
        if (!$obj_jsonstr['need_check']) {
            Enroll::send_template_message($obj_jsonstr, $customerId, $activityId, '', $openid);
        }

        /** 5. 回调是不需要返回的? */
    }

    /*
    |--------------------------------------------------------------------------
    |                           以下为该类私有方法
    |--------------------------------------------------------------------------
    */

    /**
     * 检查用户参与信息, 获得参与表的参与id
     *
     * @param $param        [actId]
     * @return int|mixed    返回参与id,如果为参与则值为0
     */
    protected function check_partake($param)
    {
        /** 1. 获得数据 */
        $activityId = $param->actId;
        $userId     = Session::$user['userId'];
        $customerId = Session::$user['customerId'];

        /** 2. 实例化数据模型 */
        Session::switchCustomer(0);
        $partakeModel    = M('miactivity_partake');
        Session::switchCustomer($customerId);

        /** 3. where */
        $partakeWhere['activityId'] = array('eq', $activityId);
        $partakeWhere['userId']     = array('eq', $userId);
        $partakeWhere['cid']        = array('eq', $customerId);

        /** 4. getField('id') */
        $partakeId = $partakeModel->where($partakeWhere)->getField('id');

        /** 5. 返回查询结果 */
        if ($partakeId) {
            return $partakeId;
        } else {
            return 0;
        }
    }

    /**
     * 报名满足一定条件后发送模板消息
     * 由于回调是静态的, 所以这个方法也要是静态的
     *
     * @param $obj_jsonstr  数据体
     * @param $customerId   cid, 去找templateId用
     * @param $activityId   活动id
     * @param $channelId    活动渠道
     * @param $openid       发给用户的openid
     */
    protected static function send_template_message($obj_jsonstr, $customerId, $activityId, $channelId, $openid)
    {
        $data['first']    = array('value' => '活动报名成功', 'color' => "#743A3A");
        $data['keyword1'] = array('value' => $obj_jsonstr['activityname'], 'color' => '#173177');
        $data['keyword2'] = array('value' => $obj_jsonstr['startTime'] . '-' . $obj_jsonstr['endTime'], 'color' => '#173177');
        $data['keyword3'] = array('value' => $obj_jsonstr['actPlace'], 'color' => '#173177');
        $data['remark']   = array('value' => '期待您的光临!', 'color' => '#008000');
        $url = C('SERVER_HOST') . 'call.html?customerId=' . $customerId . '&module=enroll&method=index&params={"actId":' . $activityId;
        empty($channelId) ? $url .= '}' : $url .=  '",chanelId:"' . $channelId . '}';
        TemplateMessage::send($openid, $customerId, 'confirmsign', $url, $data);
    }

    /**
     * 获取用户的ip以及user_agent信息
     * @return array
     */
    protected  static function getIp_agent(){
        $ipInfo = array();
        if($_SERVER['HTTP_HTTP_X_REAL_IP']){
            //nginx 代理模式下，获取客户端真实IP
            $realIp = $_SERVER['HTTP_HTTP_X_REAL_IP'];
        }elseif (isset($_SERVER['HTTP_CLIENT_IP'])) {
            //客户端的ip
            $realIp = $_SERVER['HTTP_CLIENT_IP'];
        }elseif (isset($_SERVER['HTTP_HTTP_X_FORWARDED_FOR'])) {
            //浏览当前页面的用户计算机的网关
            $arr = explode(',', $_SERVER['HTTP_HTTP_X_FORWARDED_FOR']);
            $pos = array_search('unknown',$arr);
            if(false !== $pos) unset($arr[$pos]);
            $realIp = trim($arr[0]);
        }elseif (isset($_SERVER['REMOTE_ADDR'])) {
            //浏览当前页面的用户计算机的ip地址
            $realIp = $_SERVER['REMOTE_ADDR'];
        }else{
            $realIp=$_SERVER['REMOTE_ADDR'];
        }
        $userAgent = $_SERVER['HTTP_USER_AGENT'];
        $realIpInt = bindec(decbin(ip2long($realIp)));

        //查询ip对应的地址信息
        if($realIp){
            $cid = Session::$user['customerId'];
            Session::switchCustomer(0);
            $ipInfo_table = M('ip_info');

            $map = array();
            $map['start_ip_int'] = array('elt',$realIpInt);
            $map['end_ip_int'] = array('egt',$realIpInt);
            $result = $ipInfo_table->where($map)->find();
            if($result){
                $ipInfo['province'] = $result['province'];
                $ipInfo['city'] = $result['city'];
            }else{
                Log::write('客户端ip信息----:'.print_r($_SERVER, true));
                Log::write('查询ip信息-----'.$ipInfo_table->getLastSql());
            }
            Session::switchCustomer($cid);
        }

        $ipInfo['ip_address'] = $realIp;
        $ipInfo['userAgent'] = $userAgent;
        return $ipInfo;
    }

}
